package com.hjx.logging;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * <p>Title:</p>
 * <p>Description:</p>
 *
 * @author hjx
 * @date 2020/6/11 - 17:22
 */
@Aspect
@Component
public class LoggingAspect {
    ObjectMapper mapper = new ObjectMapper();
    Logger log = LoggerFactory.getLogger(LoggingAspect.class);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    @Pointcut("@annotation(com.hjx.logging.LogAnnotation)")
    public void pointcut(){}


    @Before("pointcut()")
    public void logBefore(JoinPoint joinPoint){

        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        log.info("请求时间:"+sdf.format(new Date()));
        log.info("请求的用户"+authentication.getName());
        log.info("请求地址：" + request.getRequestURL());
        log.info("请求IP:" + request.getRemoteAddr());
        log.info("请求方法：" + request.getMethod());
        //在项目中最好记录当前操作的时间和用户
        log.info("操作所在类：" + className);
        log.info("操作所在方法：" + methodName);
        log.info("操作中的参数：");
        for (Object arg : args) {
            log.info(arg.toString());
        }
        try {
            log.info("请求入参：" + mapper.writeValueAsString(request.getParameterMap()));

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    @AfterReturning(pointcut = "pointcut()",returning = "returnVal")
    public void logReturn(JoinPoint joinPoint,Object returnVal){
//        String className = joinPoint.getTarget().getClass().getName();
//        String methodName = joinPoint.getSignature().getName();
        log.info("方法正常返回的值：" + returnVal);
    }
    @After("pointcut()")
    public void logAfter() throws Throwable {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert servletRequestAttributes != null;
        HttpServletResponse response = servletRequestAttributes.getResponse();
        assert response != null;
        log.info("响应参数：" + response.getOutputStream().toString());
    }

    @AfterThrowing(pointcut = "pointcut()",throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint,Exception e){
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        log.info("异常信息:"+e.getMessage());
        log.info("异常所在类:" + className);
        log.info("异常所在方法:" + methodName);
        log.info("异常中的参数:");
        log.info(methodName+" ");
        for (Object arg : args) {
            log.info(arg.toString());
        }
    }

}
